""" Storage_Algorithm.py: uses DAG_Reader.py to parse the sample xml file
    containing a DAG and returns the cost of store-all and the storage and
    re-computation costs of the nodes selected by the storage algorithm
"""

from DAG_Reader import DAGParser

DAG_FILE="dag.xml"

# storage/re-computation costs from Amazon Cloud
computation_cost = .085
io_cost = .12
storage_cost = .1

# formula to calculate storage costs
def calc_storage(storage, store_cost, io_cost):
    total_storage_cost = (storage * io_cost) + (storage * store_cost)
    return total_storage_cost

# formula to calculate re-computation costs
def calc_recomp(storage, reuse, store_cost, io_cost, comp_cost, comp_time):
    recomp_cost = reuse * ((storage * io_cost) + (comp_time * comp_cost)) 
    return recomp_cost

# create DAGParser object
dagGraph = DAGParser(DAG_FILE)

# find the storage cost for 'store-all'
print 'calculating costs for store-all\n' 
total_scost = 0

for ID in dagGraph.DAG:
    node = dagGraph.DAG[ID]
    storage = float(node['storage'])
    scost_per_node = calc_storage(storage, storage_cost, io_cost)
    total_scost = total_scost + scost_per_node 
    print 'node ID: ', ID, 'node storage cost: ', scost_per_node
    
print 'store-all total storage cost (in $): ', total_scost, '\n'

# storage algorithm:

""" determines the cost of storage and the cost of re-computation for all
    nodes in the DAG and stores based on the following procedure:

    if node re-computation cost > node storage cost ---> STORE
    if node re-computation cost < node storage cost ---> RE-COMPUTE (or NOT STORE)
"""

print 'calculating costs for storage algorithm\n'
total_rcost = 0
total_scost = 0

for ID in dagGraph.DAG:
    node = dagGraph.DAG[ID]
    reuse = float(node['reuse'])
    storage = float(node['storage'])
    comp_time = float(node['compUnits'])

    node_scost = calc_storage(storage, storage_cost, io_cost)
    node_rcost = calc_recomp(storage, reuse, storage_cost, io_cost,
                             computation_cost, comp_time)
    print 'node ID: ', ID, 'node recomp cost: ', node_rcost

    if node_scost > node_rcost:
        # node should NOT be stored, so add node_rcost to total_rcost
        print 'node ID: ', ID, 'node storage cost: ', node_scost, '---> NOT STORED\n'
        total_rcost = total_rcost + node_rcost
    else:
        print 'node ID: ', ID, 'node storage cost: ', node_scost, '---> STORED\n'
        total_scost = total_scost + node_scost
    
print 'storage algorithm total re-computation cost (in $): ', total_rcost
print 'storage algorithm total storage cost (in $): ', total_scost
